package com.neusoft.neuiotms.dcom.converter.insurance;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.neusoft.bizcore.web.dto.AbstractConverter;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.utils.id.BaseIdGenerator;
import com.neusoft.neuiotms.dcom.dto.hn.HnInspectionItemDTO;
import com.neusoft.neuiotms.dcom.dto.insurance.InsuranceInspectionTaskDTO;
import com.neusoft.neuiotms.dcom.dto.insurance.InsuranceInspectionTaskItemDTO;
import com.neusoft.neuiotms.dcom.dto.insurance.InsuranceRegisterTaskDTO;
import com.neusoft.neuiotms.dcom.dto.insurance.InsuranceReportTaskDTO;
import com.neusoft.neuiotms.dcom.dto.insurance.InsuranceSummaryTaskDTO;
import com.neusoft.neuiotms.dcom.model.enums.InsuranceInspectionTaskType;
import com.neusoft.neuiotms.dcom.model.enums.InsuranceReportTaskStatus;
import com.neusoft.neuiotms.dcom.model.enums.InsuranceTaskStatus;
import com.neusoft.neuiotms.dcom.model.insurance.InsuranceInspectionTask;
import com.neusoft.neuiotms.dcom.model.insurance.InsuranceRegisterTask;
import com.neusoft.neuiotms.dcom.model.insurance.InsuranceReportTask;
import com.neusoft.neuiotms.dcom.model.insurance.InsuranceSummaryTask;
import com.neusoft.neuiotms.dcom.repository.insurance.InsuranceInspectionTaskRepository;
import com.neusoft.neuiotms.dcom.repository.insurance.InsuranceRegisterTaskRepository;
import com.neusoft.neuiotms.dcom.repository.insurance.InsuranceReportTaskRepository;
import com.neusoft.neuiotms.dcom.repository.insurance.InsuranceSummaryTaskRepository;
import com.neusoft.neuiotms.dcom.service.hn.HnInspectionHealthPlanService;

@Component
public class InsuranceRegisterTaskConverter
        extends AbstractConverter<InsuranceRegisterTask, InsuranceRegisterTaskDTO> {

    @Autowired
    private BaseIdGenerator insuranceRegisterTaskCodeGenerator;
    @Autowired
    private InsuranceRegisterTaskRepository taskRepository;

    @Autowired
    private InsuranceInspectionTaskRepository insuranceInspectionTaskRepository;
    @Autowired
    private InsuranceInspectionTaskConverter inspectionTaskConverter;

    @Autowired
    private InsuranceReportTaskRepository insuranceReportTaskRepository;
    @Autowired
    private InsuranceReportTaskConverter insuranceReportTaskConverter;

    @Autowired
    private InsuranceSummaryTaskRepository insuranceSummaryTaskRepository;
    @Autowired
    private InsuranceSummaryTaskConverter insuranceSummaryTaskConverter;
    @Autowired
    private HnInspectionHealthPlanService healthPlanService;

    @Override
    public InsuranceRegisterTask toModel(final InsuranceRegisterTaskDTO dto) {

        InsuranceRegisterTask model;
        if (dto.isNew()) {
            model = new InsuranceRegisterTask();
            if (StringUtils.isEmpty(dto.getCode())) {
                model.setCode(this.insuranceRegisterTaskCodeGenerator.generateCode());
            } else {
                model.setCode(dto.getCode());
            }
        } else {
            model = this.taskRepository.getOne(dto.getId());
        }

        model.setRegisterCode(dto.getRegisterCode());
        model.setUnitCode(dto.getUnitCode());
        model.setUnitName(dto.getUnitName());
        model.setStartTime(dto.getStartTime());
        model.setEndTime(dto.getEndTime());
        model.setRegisterRemarks(dto.getRegisterRemarks());
        model.setStatus(InsuranceTaskStatus.pending);

        //巡检任务
        final List<InsuranceInspectionTask> taskListModel =
                model.getInspectionTask().stream().collect(Collectors.toList());

        taskListModel.forEach(k -> {
            model.getInspectionTask().remove(k);
            this.insuranceInspectionTaskRepository.delete(k);
        });

        //每日上报
        final List<InsuranceReportTask> reportListModel =
                model.getReportTask().stream().collect(Collectors.toList());

        reportListModel.forEach(k -> {
            model.getReportTask().remove(k);
            this.insuranceReportTaskRepository.delete(k);
        });

        //服务总结
        final List<InsuranceSummaryTask> summaryListModel =
                model.getSummaryTask().stream().collect(Collectors.toList());

        summaryListModel.forEach(k -> {
            model.getSummaryTask().remove(k);
            this.insuranceSummaryTaskRepository.delete(k);
        });

        // 计算每日上报总天数
        final int TotalReportedNum =
                (int) (((model.getEndTime().getTime() - model.getStartTime().getTime()) / (24 * 3600 * 1000)) + 1);

        for (int i = -1; i <= TotalReportedNum; i++) {
            //服务前巡检
            if (i == -1) {
                final InsuranceInspectionTaskDTO inspectionDto = new InsuranceInspectionTaskDTO();
                inspectionDto.setStartTime(this.getDateAround(model.getStartTime(), -1));
                inspectionDto.setEndTime(this.getDateAround(model.getEndTime(), -TotalReportedNum));
                inspectionDto.setCronExp(this.formatDateByPattern(inspectionDto.getStartTime()));
                inspectionDto.setStatus(InsuranceTaskStatus.notActive.name());
                inspectionDto.setType(InsuranceInspectionTaskType.before.name());
                inspectionDto.setUnitCode(model.getUnitCode());
                // 获取巡检内容
                //                final Searchable searchable = new Searchable();
                //                searchable.put("category", HnInspectionCategory.service.name());
                final List<HnInspectionItemDTO> items =
                        this.healthPlanService.findByInstitutionCode(model.getUnitCode());
                final List<InsuranceInspectionTaskItemDTO> itemValueDtos = new ArrayList<>();
                items.stream().map(t -> {
                    final InsuranceInspectionTaskItemDTO value = new InsuranceInspectionTaskItemDTO();
                    value.setItem(t);
                    return value;
                }).forEach(itemValueDtos::add);
                inspectionDto.setInspectionTaskItem(itemValueDtos);
                final InsuranceInspectionTask inspectionModel = this.inspectionTaskConverter.toModel(inspectionDto);
                inspectionModel.setRegisterTask(model);
                model.getInspectionTask().add(inspectionModel);
            }
            //服务后巡检与服务总结
            else if (i == TotalReportedNum) {
                // 服务后巡检
                final InsuranceInspectionTaskDTO inspectionDto = new InsuranceInspectionTaskDTO();
                inspectionDto.setStartTime(this.getDateAround(model.getStartTime(), TotalReportedNum));
                inspectionDto.setEndTime(this.getDateAround(model.getEndTime(), 1));
                inspectionDto.setCronExp(this.formatDateByPattern(inspectionDto.getStartTime()));
                inspectionDto.setStatus(InsuranceTaskStatus.notActive.name());
                inspectionDto.setType(InsuranceInspectionTaskType.after.name());
                inspectionDto.setUnitCode(model.getUnitCode());
                // 获取巡检内容
                //                final Searchable searchable = new Searchable();
                //                searchable.put("category", HnInspectionCategory.service.name());
                final List<HnInspectionItemDTO> items =
                        this.healthPlanService.findByInstitutionCode(model.getUnitCode());
                final List<InsuranceInspectionTaskItemDTO> itemValueDtos = new ArrayList<>();
                items.stream().map(t -> {
                    final InsuranceInspectionTaskItemDTO value = new InsuranceInspectionTaskItemDTO();
                    value.setItem(t);
                    return value;
                }).forEach(itemValueDtos::add);
                inspectionDto.setInspectionTaskItem(itemValueDtos);
                final InsuranceInspectionTask inspectionModel = this.inspectionTaskConverter.toModel(inspectionDto);
                inspectionModel.setRegisterTask(model);
                model.getInspectionTask().add(inspectionModel);
                // 服务总结
                final InsuranceSummaryTaskDTO summaryDto = new InsuranceSummaryTaskDTO();
                summaryDto.setStartTime(model.getStartTime());
                summaryDto.setEndTime(model.getEndTime());
                summaryDto.setStatus(InsuranceTaskStatus.notActive.name());
                summaryDto.setUnitCode(model.getUnitCode());
                final InsuranceSummaryTask summaryModel = this.insuranceSummaryTaskConverter.toModel(summaryDto);
                summaryModel.setRegisterTask(model);
                model.getSummaryTask().add(summaryModel);
            }
            // 每日上报
            else if ((i > -1) && (i < TotalReportedNum)) {
                final InsuranceReportTaskDTO reportDto = new InsuranceReportTaskDTO();
                reportDto.setStartTime(this.getDateAround(model.getStartTime(), i));
                reportDto.setEndTime(this.getDateAround(model.getEndTime(), (i + 1) - TotalReportedNum));
                reportDto.setCronExp(this.formatDateByPattern(this.getDateAround(model.getStartTime(), i)));
                reportDto.setSorting(i + 1);
                reportDto.setStatus(InsuranceReportTaskStatus.notActive.name());
                reportDto.setUnitCode(model.getUnitCode());
                final InsuranceReportTask reportModel = this.insuranceReportTaskConverter.toModel(reportDto);
                reportModel.setRegisterTask(model);
                model.getReportTask().add(reportModel);
            }
        }

        return model;
    }

    @Override
    public InsuranceRegisterTaskDTO toDTO(final InsuranceRegisterTask model, final boolean forListView) {

        final InsuranceRegisterTaskDTO dto = new InsuranceRegisterTaskDTO();

        dto.setId(model.getId());
        dto.setCode(model.getCode());
        dto.setRegisterCode(model.getRegisterCode());
        dto.setUnitCode(model.getUnitCode());
        dto.setUnitName(model.getUnitName());
        dto.setStartTime(model.getStartTime());
        dto.setEndTime(model.getEndTime());
        dto.setRegisterRemarks(model.getRegisterRemarks());
        dto.setStatus(model.getStatus().name());

        //重保服务巡检任务状态
        final List<InsuranceInspectionTask> inspectionTaskLists = this.insuranceInspectionTaskRepository
                .findByRegisterTaskId(model.getId());
        if ((null != inspectionTaskLists) && (inspectionTaskLists.size() == 2)) {
            // 一个重保服务登记，有且仅有两个重保服务巡检任务
            inspectionTaskLists.forEach(e -> {
                if (e.getType().equals(InsuranceInspectionTaskType.before)) {
                    // 重保服务前巡检
                    dto.setBeforeInspectionStatus(e.getStatus().name());
                } else {
                    // 重保服务后巡检
                    dto.setAfterInspectionStatus(e.getStatus().name());
                }
            });
        } else {
            throw new UnitedException("此重保服务数据有问题");
        }

        //每日上报任务
        final List<InsuranceReportTask> totalLists =
                this.insuranceReportTaskRepository.findByRegisterTaskId(model.getId());
        if ((null != totalLists) && (totalLists.size() > 0)) {
            //每日上报任务总数
            dto.setTotalReportedNum(totalLists.size());
            final List<InsuranceReportTask> completeList =
                    totalLists.stream().filter(item -> item.getStatus().equals(InsuranceReportTaskStatus.reported))
                            .collect(Collectors.toList());
            //上报任务完成数
            if (null != completeList) {
                dto.setCompleteReportedNum(completeList.size());
            } else {
                dto.setCompleteReportedNum(0);
            }
        } else {
            throw new UnitedException("此重保服务数据有问题");
        }

        //服务总结
        final InsuranceSummaryTask summaryTaskModel =
                this.insuranceSummaryTaskRepository.findByRegisterTaskId(model.getId());
        dto.setSummaryStatus(summaryTaskModel.getStatus().name());

        return dto;
    }

    /***
     * @see 功能描述：根据指定日期获得前几天或后几天
     * @param date,day
     * @return
     */
    private Date getDateAround(final Date d, final int day) {
        //        final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        final Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.set(Calendar.DATE, now.get(Calendar.DATE) + day);//+后 -前
        return now.getTime();
    }

    /***
     * @see 功能描述：日期转换cron表达式
     * @param date
     * @return
     */
    private String formatDateByPattern(final Date date) {
        final SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ? *");
        String formatTimeStr = null;
        if (Objects.nonNull(date)) {
            formatTimeStr = sdf.format(date);
        }
        return formatTimeStr;
    }
}
